/**
 * 在这里定义和用户相关的路由处理函数，供 /router/user.js 模块进行调用
 */
const db = require('../db/index')
//给密码加密
const bcrypt = require('bcryptjs')
// 用这个包来生成 Token 字符串
const jwt = require('jsonwebtoken')
// 导入配置文件
const config = require('../config')

/**
 * 注册用户的处理函数
 * 注意内部执行时只能send一次，对于一个请求send多次时会报错
 * 之所以 return res.send是为了在res.send执行后 函数终止执行
 * 多用return还有一个好处是 不用写那么多的else 逻辑能在一个纵向平面上
 */
exports.regUser = (req, res) => {
  // 接收表单数据
  const userinfo = req.body
  // 判断数据是否合法
  if (!userinfo.username || !userinfo.password) {
    return res.cc('用户名或密码不能为空！')
  }

  // 对用户的密码,进行 bcrype 加密，返回值是加密之后的密码字符串
  userinfo.password = bcrypt.hashSync(userinfo.password, 10)

  let sql = `select * from ev_users where username=?`
  db.query(sql, [userinfo.username], function (err, results) {
    // 执行 SQL 语句失败
    if (err) {
      return res.cc(err)
    }
    // 用户名被占用
    if (results.length > 0) {
      return res.cc('用户名被占用，请更换其他用户名！')
    }

    // 用户名可用 写入数据库
    sql = 'insert into ev_users (username,password) values (?, ?)'
    db.query(sql, [userinfo.username, userinfo.password], (err2, result2) => {
      if (err2) return res.cc(err2);
      //执行sql语句 影响行数不为1 说明写表有问题
      if (result2.affectedRows !== 1) return res.cc('注册用户失败')

      res.cc('注册成功', 0)
      // res.send({ status: 0, message: '注册成功' })
    })
  })
}

// 登录的处理函数
exports.login = (req, res) => {
  const userinfo = req.body
  const sql = `select * from ev_users where username=?`
  db.query(sql, userinfo.username, function (err, results) {
    // 执行 SQL 语句失败
    if (err) return res.cc(err)
    // 执行 SQL 语句成功，但是查询到数据条数不等于 1
    if (results.length !== 1) return res.cc('登录失败！')
    // TODO：判断用户输入的登录密码是否和数据库中的密码一致

    // 拿着用户输入的密码,和数据库中存储的密码进行对比//***顺序很重要 不要写反******
    const compareResult = bcrypt.compareSync(userinfo.password, results[0].password)
    // 如果对比的结果等于 false, 则证明用户输入的密码错误
    if (!compareResult) {
      return res.cc('登录失败！')
    }
    // TODO：登录成功，生成 Token 字符串
    // 剔除完毕之后，user 中只保留了用户的 id, username, nickname, email 这四个属性的值
    // password:'' 或 password:null 还是会被塞进token的payload，只有解构后 password: undefined 覆盖原值，jwt转换后才没有该属性
    const user = { ...results[0], password: undefined, user_pic: undefined }
    // let user = { id: results[0].id, username: results[0].username, nickname: results[0].nickname, email: results[0].email }
    // 生成 Token 字符串
    const tokenStr = jwt.sign(user, config.jwtSecretKey, {
      expiresIn: config.expiresIn, // token 有效期为 10 个小时
    })
    res.send({
      code: 0,
      message: '登录成功！',
      // 为了方便客户端使用 Token，在服务器端直接拼接上 Bearer 的前缀
      token: 'Bearer ' + tokenStr,
    })

  })
}